package com.xlh.service.courseTest.impl;

import cn.hutool.core.util.URLUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import com.xlh.common.Result;
import com.xlh.common.ResultEnum;
import com.xlh.dao.courseTest.GradeStatisticsMapperExt;
import com.xlh.dao.user.ext.UserMapperExt;
import com.xlh.dto.PageDTO;
import com.xlh.dto.courseTest.GradeStatisticsExcelListDTO;
import com.xlh.dto.courseTest.GradeStatisticsListDTO;
import com.xlh.dto.courseTest.PaperAnswerSheetDTO;
import com.xlh.dto.courseTest.check.StudentBaseListDTO;
import com.xlh.dto.courseTest.check.StudentListDTO;
import com.xlh.dto.user.UserInfoDTO;
import com.xlh.enums.courseTest.PaperStatusEnum;
import com.xlh.enums.courseTest.StatisticsExcelCellEnum;
import com.xlh.enums.user.ClassStatusEnum;
import com.xlh.exception.common.GlobalException;
import com.xlh.pojo.course.ChapterBasic;
import com.xlh.pojo.courseTest.ExperimentReport;
import com.xlh.pojo.courseTest.Practice;
import com.xlh.service.course.ChapterService;
import com.xlh.service.courseTest.ExperimentService;
import com.xlh.service.courseTest.GradeStatisticsService;
import com.xlh.service.courseTest.PaperAnswerSheetService;
import com.xlh.service.courseTest.PracticeService;
import com.xlh.util.BeanUtil;
import com.xlh.util.ExcelsUtil;
import org.apache.commons.collections.CollectionUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author zhr 2019/4/9
 */
@Service
public class GradeStatisticsServiceImpl implements GradeStatisticsService {

    private static Logger logger = LoggerFactory.getLogger(GradeStatisticsServiceImpl.class);

    private static final String FILE_NAME = "成绩统计.xls";

    @Autowired
    private ChapterService chapterService;
    @Autowired
    private PracticeService practiceService;
    @Autowired
    private ExperimentService experimentService;
    @Autowired
    private PaperAnswerSheetService answerSheetService;

    @Autowired
    private GradeStatisticsMapperExt mapperExt;
    @Autowired
    private UserMapperExt userMapperExt;

    @Override
    public PageDTO<GradeStatisticsListDTO> list(Integer pageNum, Integer pageSize, Long courseId, List<Long> classes, String userInfo) {
        PageHelper.startPage(pageNum, pageSize);

        // 查询列表
        List<GradeStatisticsListDTO> resultList = getList(courseId, classes, userInfo);

        PageInfo<GradeStatisticsListDTO> pageInfo = new PageInfo<>(resultList);
        return new PageDTO<>(pageInfo);
    }

    private List<GradeStatisticsListDTO> getList(Long courseId, List<Long> classes, String userInfo) {
        // 查询班级学生等基本信息
        List<GradeStatisticsListDTO> resultList = mapperExt.listStudent(courseId, classes, userInfo);
        resultList.forEach(dto -> dto.setEndedMessage(
                dto.getEnded() ? ClassStatusEnum.ENDED.getMessage() : ClassStatusEnum.UNFINISHED.getMessage()));
        // 获取课程的全部章节
        List<ChapterBasic> chapterBasics = chapterService.getChapterBasic(courseId, null, null, null);
        Map<Long, String> chapterIdNameMap = chapterBasics.stream().collect(Collectors.toMap(ChapterBasic::getId, ChapterBasic::getName));
        List<Long> chapterIds = chapterBasics.stream().map(ChapterBasic::getId).collect(Collectors.toList());

        // 获取随堂练习信息
        List<Practice> practiceList = practiceService.selectByChapterIdsWithoutBlobs(chapterIds);
        Map<Long, List<Practice>> studentIdPracticeListMap = BeanUtil.aggByKeyToList("studentId", practiceList);

        // 获取实验报告信息
        List<ExperimentReport> reportList = experimentService.selectByChapterIds(chapterIds);
        Map<Long, List<ExperimentReport>> studentIdReportListMap = BeanUtil.aggByKeyToList("studentId", reportList);

        // 获取考试内容
        List<PaperAnswerSheetDTO> answerSheetList = answerSheetService.selectByCourseIdPaperStat(courseId, PaperStatusEnum.READ.getCode());
        Map<Long, List<PaperAnswerSheetDTO>> userIdAnswerSheetMap = BeanUtil.aggByKeyToList("studentId", answerSheetList);

        // 封装数据
        resultList.forEach(result -> result.convert(
                chapterIdNameMap,
                studentIdPracticeListMap.get(result.getUserClassId()),
                studentIdReportListMap.get(result.getUserClassId()),
                userIdAnswerSheetMap.get(result.getStudentId()))
        );

        return resultList;
    }

    @Override
    public List<StudentBaseListDTO> listStudentBase(Long courseId, Long userId) {
        List<StudentBaseListDTO> practiceList = practiceService.listStudentBase(courseId, userId);
        List<StudentBaseListDTO> reportList = experimentService.listStudentBase(courseId, userId);
        List<StudentBaseListDTO> resultList = Lists.newArrayList(practiceList);
        resultList.addAll(reportList);
        return resultList;
    }
    @Override
    public List<StudentListDTO> listStudentBaseOther(Long userId, Long courseId, Long chapterId, Long classId) {
        List<StudentListDTO> practice = practiceService.listStudentBaseOther(userId,courseId, chapterId,classId);
        return practice;
    }

    @Override
    public List<StudentListDTO> listStudentBaseStatistics(Long userId, Long courseId, Long chapterId, Long classId, Integer pageSize, Integer currentPage) {
        List<UserInfoDTO> userInfoDTOS = userMapperExt.listClassUser(null, Lists.newArrayList(1), Lists.newArrayList(classId), false);
        List<StudentListDTO> practice = practiceService.listStudentBaseOther(userId,courseId, chapterId,classId);

        List<String> collect = practice.stream().map(StudentListDTO::getUserNumber).collect(Collectors.toList());
        Integer sum = practice.stream().collect(Collectors.summingInt(StudentListDTO::getScore));
        Double avg=0.0;
        if (practice.size()==0){
            throw new GlobalException(ResultEnum.CLASS_NOT_PASS);
        }

        List<StudentListDTO> list=Lists.newArrayList();
        List<StudentListDTO> listall=Lists.newArrayList();
        List<StudentListDTO> listall1=Lists.newArrayList();
        userInfoDTOS.stream().forEach(
                UserInfoDTO->{
                    if (!collect.contains(UserInfoDTO.getUserNumber())){
                        StudentListDTO practiceDTO= new StudentListDTO();
                        practiceDTO.setScore(0);
                        practiceDTO.setUserName(UserInfoDTO.getName());
                        practiceDTO.setUserNumber(UserInfoDTO.getUserNumber());
                        list.add(practiceDTO);
                    }
                }
        );
        if (practice.size()==0){
            avg=0.0;
        }else {
            BigDecimal b1 = new BigDecimal(sum);
            BigDecimal b2 = new BigDecimal(practice.size());
            avg= b1.divide(b2, 2, BigDecimal.ROUND_HALF_UP).doubleValue();
        }
        listall.addAll(practice);
        listall.addAll(list);
        if (listall!=null){
            for (int i = 0; i < listall.size(); i++) {
                listall.get(i).setRank(i);
            }
        }
        if (listall!=null&&listall.size()>0){
            listall.get(0).setAvg(avg);
            listall.get(0).setCount(practice.size()+"/"+userInfoDTOS.size());
        }
        if (pageSize!=null&&pageSize!=0) {

            if (listall != null && listall.size() > 0) {

                int currIdx = (currentPage > 1 ? (currentPage - 1) * pageSize : 0);
                for (int i = 0; i < pageSize && i < listall.size() - currIdx; i++) {

                    StudentListDTO data = listall.get(currIdx + i);
                    listall1.add(data);
                }
            }
            return  listall1;
        }

        return listall;
    }

    @Override
    public Result outputList(Long courseId, List<Long> classes, String userInfo) {
        // 查询列表
        List<GradeStatisticsListDTO> resultList = getList(courseId, classes, userInfo);

        // 转化列表为excel模板列表
        List<GradeStatisticsExcelListDTO> excelList = batchConvert(resultList);

        HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();

        // 导出excel
        try (Workbook wb = ExcelsUtil.createWorkBook(excelList, StatisticsExcelCellEnum.class)) {
            response.setContentType("application/x-download");
            response.addHeader("Content-Disposition", "attachment;filename=" + FILE_NAME + ";filename*=UTF-8''" + URLUtil.encode(FILE_NAME));
            wb.write(response.getOutputStream());
        } catch (IOException | IllegalAccessException e) {
            logger.error(e.getMessage(), e);
            return Result.error(ResultEnum.EXCEL_OUTPUT_EXCEPTION);
        }

        return Result.success();
    }

    @Override
    public void download(List<StudentListDTO> studentListDTOS, String courseName, String chapterName, String className) {

        List<Map<String, Object>> excelList = new ArrayList<>();
        Map<String, Object> header = new HashMap<>();
        header.put("sheetName", "随堂练习统计");
        excelList.add(header);
        for (StudentListDTO studentListDTO : studentListDTOS) {
            Map<String, Object> line = new HashMap<>();
            line.put("rank", studentListDTO.getRank()+1);
            line.put("userNumber", studentListDTO.getUserNumber());
            line.put("userName", studentListDTO.getUserName());
            line.put("score", studentListDTO.getScore());
            line.put("courseName", courseName);
            line.put("chapterName", chapterName);
            line.put("className", className);
            excelList.add(line);
        }

        String[] columnNames = {"排名", "学号", "姓名", "随堂练习分数"};
        String[] keys = {"rank", "userNumber", "userName", "score"};
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
        ExcelsUtil.ExcelSingleOutputStreamPractice(excelList, keys, columnNames, "随堂练习统计", request, response);
    }

    private List<GradeStatisticsExcelListDTO> batchConvert(List<GradeStatisticsListDTO> list) {
        List<GradeStatisticsExcelListDTO> resultList = Lists.newArrayList();
        if (CollectionUtils.isNotEmpty(list)) {
            for (GradeStatisticsListDTO dto : list) {
                resultList.add(new GradeStatisticsExcelListDTO(dto));
            }
        }
        return resultList;
    }
}
